package com.gxa.learning.pc.service.impl;

import com.gxa.learning.core.pojo.Comment;
import com.gxa.learning.core.pojo.CommentVo;
import com.gxa.learning.core.pojo.User;
import com.gxa.learning.core.util.JsonUtil;
import com.gxa.learning.pc.service.ProjectRemarkService;
import com.gxa.learning.pc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author YXQ
 * @date 2021/12/16 8:45
 */
@Service("projectRemarkService")
public class ProjectRemarkServiceImpl implements ProjectRemarkService {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    UserService userService;

    /**
     * 用于评论主体的类(Hash)的辅助Key--->"project:":课程id
     * Key: course:课程id:remark:id  ObjectKey: 字段 Value:字段值
     * Key: course:课程id:remark:id 表示某门课程的某条评论
     */
    private final static String REMARK_PROJECT = "project:";

    /**
     * 用于评论主体的类(Hash)的辅助Key--->":remark:"
     * Key: course:课程id:remark:id 表示某门课程的某条评论
     */
    private final static String REMARK = ":remark:";

    /**
     * 用于评论自增的的辅助Key--->:remarkId
     * Key: course:课程id:remarkId  Value: id
     */
    private final static String REMARK_ID = ":remarkId";

    /**
     * 用户点赞的列表(Set)的Key
     * Key:userId : likeRemark Value: courseId:remarkId
     * 键:用户的收藏列表 值: XX课程:XX评论
     */
    private final static String LIKE_PROJECT_REMARK = ":likeProjectRemark";

    @Override
    public void comment(Long userId, Long projectId, String remark, Long pId, String reply) {
        // String的操作集--->做评论自增的id
        ValueOperations<String, Object> stringOps = redisTemplate.opsForValue();
        // 准备自增的评论id的Key--->course:课程id:remarkId
        String remarkIdKey = REMARK_PROJECT + projectId + REMARK_ID;
        // 先获取这个值是否存在
        Object o = stringOps.get(remarkIdKey);
        // 不存在时新建，存在时自增+1
        if (o == null) {
            // 不存在时新建
            stringOps.set(remarkIdKey, 1);
        } else {
            // 存在时自增+1
            stringOps.increment(remarkIdKey);
        }
        // 拿到这个id值作为评论的自增的id值
        String idString = Objects.requireNonNull(stringOps.get(remarkIdKey)).toString();
        // 将String类型的id转化为Long类型
        Long id = Long.parseLong(idString);
        // Hash的操作集--->做每条评论的内容
        HashOperations<String, Object, Object> hashOps = redisTemplate.opsForHash();
        // 评论的主体通过Hash来做
        // Key: course:课程id:remark:id  ObjectKey: 字段 Value:字段值
        // 给XX课程下，添加某条评论的记录
        // id 评论的编号
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "id", id);
        // userId 用户的编号,发表评论的人
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "userId", userId);
        // courseId 课程的编号
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "projectId", projectId);
        // remark 评论的内容
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "remark", remark);
        // pId 直接评论->pId为0,回复->pid为一级评论的编号
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "pid", pId);
        // reply 被回复的人
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "reply", reply);
        // star 评论刚发表时，点赞数量为0
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "star", 0);
        // 发表评论的时间 为当前时间
        Date createTime = new Date();
        // 设置日期格式化的格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将日期格式化
        String create = simpleDateFormat.format(createTime);
        // create 发表评论的时间
        hashOps.put(REMARK_PROJECT + projectId + REMARK + id, "create", create);
    }

    @Override
    public void likeComment(Long userId, Long projectId, Long remarkId, Integer isLike) {
        // Set的操作集--->做用户点赞过的评论列表
        SetOperations<String, Object> setOps = redisTemplate.opsForSet();
        // Hash的操作集--->获取每条评论的内容--->做点赞量的增加和减少
        HashOperations<String, Object, Object> hashOps = redisTemplate.opsForHash();
        // isLike---> 1点赞 0取消点赞
        if (isLike == 1) {
            // 表示用户点赞
            // 用户点赞列表,向set中添加：一条评论的id
            setOps.add(userId + LIKE_PROJECT_REMARK + projectId, remarkId);
            // 用户每次点赞会让点赞的评论对应的Hash的数据中的点赞量+1
            hashOps.increment(REMARK_PROJECT + projectId + REMARK + remarkId, "star", 1);
        } else if (isLike == 0) {
            // 表示用户取消点赞
            // 用户点赞列表,向set中去除：一条评论的id
            setOps.remove(userId + LIKE_PROJECT_REMARK + projectId, remarkId);
            // 用户每次取消点赞会让点赞的评论对应的Hash的数据中的点赞量-1
            hashOps.increment(REMARK_PROJECT + projectId + REMARK + remarkId, "star", -1);
        }
    }

    @Override
    public List<CommentVo> getCommentList(Long userId, Long projectId) {
        // Set的操作集--->做用户点赞过的评论列表
        // 看评论列表中的每条评论的id是否存在于这个点赞列表中
        SetOperations<String, Object> setOps = redisTemplate.opsForSet();
        // Hash的操作集--->获取每条评论的内容
        HashOperations<String, Object, Object> hashOps = redisTemplate.opsForHash();
        // String的操作集--->查询用户信息
        ValueOperations<String, Object> stringOps = redisTemplate.opsForValue();
        // 获取该课程下的所有评论装入List中
        List<CommentVo> list = new ArrayList<>(10);
        // 循环变量
        int i = 1;
        // 死循环获取某门课程下的所有的评论
        while (true) {
            // 拿到Key下的所有字段
            Set<Object> keys = hashOps.keys(REMARK_PROJECT + projectId + REMARK + i);
            // 拿到Key为空是结束循环
            if (keys.isEmpty()) {
                // 结束循环
                break;
            }
            // 拿到对应Hash将这个Hash对象转化为Map
            // 获取这些字段值 id,userId,courseId,remark,pid,reply,star,create
            Map<Object, Object> entries = hashOps.entries(REMARK_PROJECT + projectId + REMARK + i);
            // 放到评论的Vo对象上
            CommentVo commentVo = new CommentVo();
            // 取出对应值存入对象中
            // 获取id属性
            Long id = Long.parseLong(entries.get("id").toString());
            // 同时向comment和commentVo中添加
            // comment给redis服务,commentVo服务
            // 添加到属性字段中
            // 添加评论的id
            commentVo.setId(id);
            // 获取用户的编号
            Long userId1 = Long.parseLong(entries.get("userId").toString());
            // 添加用户的编号
            commentVo.setUserid(userId1);
            // 根据用户编号查询redis中是否存在用户信息，不存在则添加
            Object o = stringOps.get(MainServiceImpl.USER + userId1);
            // 如果不存在
            if (o == null) {
                // 不存在，到数据库查询用户信息，存入redis中
                User user = userService.selectById(userId1);
                // 如果用户存在将user转化成字符串
                if (user == null || user.getId() == null) {
                    // 该用户已注销
                    commentVo.setUserName("该用户已注销");
                    commentVo.setUserHeadPhoto("XXXX.jpg");
                } else {
                    // 第一次直接加到对象上
                    // 获取用户名字和头像存入redis中
                    commentVo.setUserName(user.getName());
                    commentVo.setUserHeadPhoto(user.getPhoto());
                    // 存在将对象转成字符串存入redis中
                    String s = JsonUtil.objectToString(user);
                    // 存入redis
                    stringOps.set(MainServiceImpl.USER + userId1, s);
                }
            } else {
                // 存在则将数据转化成对象赋值给Vo
                String s = o.toString();
                // 将字符串转化成对象
                User user = JsonUtil.stringToObject(s, User.class);
                // 获取用户名字和头像存入redis中
                commentVo.setUserName(user.getName());
                commentVo.setUserHeadPhoto(user.getPhoto());
            }
            // 设置培训id
            commentVo.setProjectId(Long.parseLong(entries.get("projectId").toString()));
            // 设置评论内容
            commentVo.setRemark(entries.get("remark").toString());
            // 设置父id
            commentVo.setPId(Long.parseLong(entries.get("pid").toString()));
            // 设置回复人
            commentVo.setReply(entries.get("reply").toString());
            System.out.println(entries.get("reply"));
            System.out.println("------------------------");
            // 设置点赞数
            commentVo.setStar(Long.parseLong(entries.get("star").toString()));
            // 存入日期对象
            String create = entries.get("create").toString();
            // 将字符串转化为日期为 Timestamp 格式
            Timestamp timestamp = Timestamp.valueOf(create);
            // 转化为日期对象
            Date date = new Date(timestamp.getTime());
            // 存入对象中
            commentVo.setCreate(date);
            // 默认没有点赞此评论
            commentVo.setIsLike(0);
            // 检查这个对象是否被这个用户收藏
            Boolean member = setOps.isMember(userId + LIKE_PROJECT_REMARK + projectId, id);
            // 检查空
            if (member != null) {
                // 如果存在返回数据中点赞为1
                if (member) {
                    // 表示确定点赞
                    commentVo.setIsLike(1);
                }
            }
            // 添加到集合中
            list.add(commentVo);
            // 循环变量自增
            i++;
        }
        return list;
    }
}
